﻿function ECommerceApi(urls, userId) {

    var self = this;

    var encodedUserId = new Base64().encode(new UTF8().getBytes(userId));

    var stdRequest = function (verb, url, data, success, error, opts) {
        var dataType = (opts ? opts.dataType : '') || 'json';
        var options = {
            url: url,
            type: verb,
            data: data,
            traditional: verb == 'GET',
            success: function () {
                this._products = arguments[0];
                if (success)
                    success(arguments[0]);
            },
            error: function (jqXhr, statusText, errorText) {
                if (error) {
                    error();
                }
            }
        };

        if (verb == 'POST' || verb == 'PUT') {
            if (data) {
                options.data = JSON.stringify(data);
                options.dataType = dataType;
                options.contentType = 'application/json';
            }
        } else if (verb == 'DELETE') {
            options.dataType = 'text';
            options.contentType = 'text/plain';
        } else {
            options.data = data;
        }

        $.ajax(options);
    };

    var cart = (function () {

        var cartUrl = urls.cartsUri + 'api/cart/' + encodedUserId + '/';

        function get(success, failed) {
            stdRequest('GET', cartUrl, null, success, failed);
        }

        function postItem(cartItem, success, failed) {
            stdRequest('POST', cartUrl + 'items/', cartItem, success, failed);
        }

        function putItem(prodId, cartItem, success, failed) {
            stdRequest('PUT', cartUrl + 'items/' + prodId, cartItem, success, failed);
        }

        function deleteItem(productId, success, failed) {
            stdRequest('DELETE', cartUrl + 'items/' + productId, null, success, failed);
        }

        function checkout(success, failed) {
            stdRequest('POST', cartUrl + 'checkout/', null, success, failed);
        }

        return {
            get: get,
            postItem: postItem,
            putItem: putItem,
            deleteItem: deleteItem,
            checkout: checkout
        };

    })();

    var orders = (function () {

        var url = urls.ordersUri + 'api/orders/';
        var ordersUrl = url + encodedUserId + '/';

        function list(success, failed) {
            stdRequest('GET', ordersUrl, null, success, failed);
        }

        function getById(orderId, success, failed) {
            stdRequest('GET', ordersUrl + orderId, null, success, failed);
        }

        return {
            list: list,
            getById: getById
        };

    })();

    var reviews = (function () {

        var url = urls.productsUri + 'api/product/';

        function listForProduct(productId, pageNumber, pageSize, success, failed) {
            stdRequest('GET', url + productId + '/reviews/', {
                pageSize: pageSize,
                pageIndex: pageNumber - 1
            }, success, failed);
        }

        function updateReview(productId, reviewId, review, success, failed) {
            stdRequest('PUT', url + productId + '/reviews/' + reviewId, review, success, failed, {
                dataType: 'text'
            });
        }

        function removeReview(productId, reviewId, success, failed) {
            stdRequest('DELETE', url + productId + '/reviews/' + reviewId, null, success, failed);
        }

        function getById(productId, reviewId, success, failed) {
            stdRequest('GET', url + productId + '/reviews/' + reviewId, null, success, failed);
        }

        function submit(productId, data, success, failed) {
            stdRequest('POST', url + productId + '/reviews/', data, success, failed, {
                dataType: 'text'
            });
        }

        return {
            listForProduct: listForProduct,
            updateReview: updateReview,
            removeReview: removeReview,
            getById: getById,
            submit: submit
        };

    })();

    var products = (function () {

        var url = urls.productsUri + 'api/product/';

        function getById(productId, success, failed) {
            stdRequest('GET', url + productId, null, success, failed);
        }

        function getDetailsById(productId, success, failed) {
            stdRequest('GET', url + productId + '/details', null, success, failed);
        }
        
        function updateProduct(productId, product, success, failed) {
            stdRequest('PUT', url + productId, product, success, failed, {
                dataType: 'text'
            });
        }

        function createProduct(product, success, failed) {
            stdRequest('POST', url, product, success, failed, {
                dataType: 'text'
            });
        }

        function removeProduct(productId, success, failed) {
            stdRequest('DELETE', url + productId, null, success, failed);
        }

        function listForTag(tag, pageNumber, pageSize, success, failed) {
            stdRequest('GET', url + 'search/tag', {
                key: tag,
                pageSize: pageSize,
                pageIndex: pageNumber - 1
            }, success, failed);
        }

        function getTags(success, failed) {
            stdRequest('GET', url + 'tags/', null, success, failed);
        }

        function searchProductsPage(term, pageNumber, pageSize, success, failed) {
            stdRequest('GET', url + 'search/name', {
                key: term,
                pageSize: pageSize,
                pageIndex: pageNumber - 1
            }, success, failed);
        }

        return {
            getById: getById,
            getDetailsById: getDetailsById,
            updateProduct: updateProduct,
            createProduct: createProduct,
            removeProduct: removeProduct,
            listForTag: listForTag,
            getTags: getTags,
            searchProductsPage: searchProductsPage
        };
    })();

    var recommendations = (function () {

        var url = urls.recommendationsUri;

        function getByIds(productIds, success, failed) {
            stdRequest('GET', url + 'api/recommendation/', { prodId: productIds }, success, failed);
        }

        function addTraversal(fromId, toId, success, failed) {
            stdRequest('POST', url + 'api/recommendation/traversal', { from: fromId, to: toId }, success, failed);
        }

        return {
            getByIds: getByIds,
            addTraversal: addTraversal
        };
    })();

    var session = (function () {

        var url = urls.sessionUri + 'api/vieweditems/';

        function getByUser(count, success, failed) {
            var data = {};
            if (count) {
                data.count = count;
            }
            stdRequest('GET', url + encodedUserId + '/', data, success, failed);
        }

        function postItem(sessionItem, success, failed) {
            stdRequest('POST', url, sessionItem, success, failed);
        }

        return {
            getByUser: getByUser,
            postItem: postItem
        };

    })();

    function getProducts(success, failed) {
        stdRequest('GET', 'products', null, success, failed);
    }

    self.getProducts = getProducts;
    self.products = products;
    self.recommendations = recommendations;
    self.cart = cart;
    self.orders = orders;
    self.reviews = reviews;
    self.session = session;
}